
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>spring底层原理 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>spring底层原理 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">Spring中的“控制反转”（IoC）核心思想是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">控制反转的核心思想是把对象的创建和生命周期管理权限转交给IOC容器。开发者不再通过 `new` 关键字手动创建对象，而是由IOC容器来统一完成，需要对象时直接从容器中获取。</div>
          </div>
          <div class="card-source">来源: IOC -> 概念</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是依赖注入（DI）思想，它主要解决了什么问题？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">DI（Dependency Injection）即依赖注入，是IoC的一种实现方式。它主要解决的是bean与bean之间的依赖关系问题，例如在一个Controller中需要使用一个Service实例的场景。</div>
          </div>
          <div class="card-source">来源: IOC -> 思想</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在Spring中，使用哪些注解可以标识一个类交由IOC容器管理？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">使用 @Controller、@RestController、@Service、@Repository、@Bean、@Component 或 @Configration 注解修饰的类，代表着该类将被IOC容器来管理。</div>
          </div>
          <div class="card-source">来源: IOC -> 举例说明</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是面向切面编程（AOP）？它能带来哪些好处？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">AOP是面向切面编程，其思想是动态地在某个方法执行之前或之后执行一些通用逻辑（如日志、事务）。它的好处包括：实现解耦、将核心业务与系统级服务（横切关注点）分开、使业务代码只关注核心业务逻辑。</div>
          </div>
          <div class="card-source">来源: AOP -> 概念</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">Spring AOP的底层实现机制是什么？它如何智能地选择实现方式？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">AOP的底层实现机制是动态代理。Spring会进行智能选择：如果目标对象实现了接口，就使用JDK动态代理；如果目标对象没有实现接口，就使用CGLIB来创建代理。</div>
          </div>
          <div class="card-source">来源: AOP -> 底层实现</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">为什么JDK动态代理要求目标对象必须实现一个接口？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为Java语言是单继承的。JDK动态代理在运行时生成的代理类已经继承了 `java.lang.reflect.Proxy` 类，因此它无法再继承其他类。为了扩展功能，它只能通过实现目标对象所实现的接口来达到代理的目的。</div>
          </div>
          <div class="card-source">来源: 动态代理的实现 -> JDK实现</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">AOP中的环绕通知（Around Advice）和前置通知（Before Advice）之间最关键的区别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">最关键的区别在于环绕通知可以控制目标方法是否被调用，而前置通知不能。在环绕通知中，可以通过编程决定是否继续执行目标方法（调用 `proceedingJoinPoint.proceed()`），而前置通知执行后，目标方法总是会被调用。</div>
          </div>
          <div class="card-source">来源: AOP -> AOP通知(增强)类型</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">CGLIB实现动态代理的原理是什么？它与JDK代理相比有什么不同？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">CGLIB通过动态地为目标对象创建一个子类来实现代理，并在子类中重写父类的方法以织入增强逻辑。与JDK代理最大的不同是，CGLIB不要求目标对象实现接口。</div>
          </div>
          <div class="card-source">来源: 动态代理的实现 -> Cglib实现</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">请列举一些Spring AOP的典型使用场景。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">文档中提到的AOP典型使用场景包括：1、事务控制；2、日志记录；3、权限控制；4、代理的创建。</div>
          </div>
          <div class="card-source">来源: AOP -> AOP使用场景</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
